<template>
  <div>
    <a-card :bordered="false" :bodyStyle="{ height: '100%' }" :style="{ height: '100%' }">
      <a-card-grid style="width:25%;textAlign:'center';height:100%">
        <div style="height:100%">
          <a-input-search style="margin-bottom: 8px" v-model="searchValue" placeholder="请输入功能标题查询" @change="onTreeSearchChange" />
          <div>
            <div class="hh-scroll-hover" style="height:460px">
              <div>
                <a-tree
                  showLine
                  @expand="onExpand"
                  :expandedKeys="expandedKeys"
                  :selectedKeys="selectedKeys"
                  :autoExpandParent="autoExpandParent"
                  :treeData="functionList"
                  draggable
                  @dragenter="onDragEnter"
                  @drop="onDrop"
                  @select="this.onFunctionTreeSelect"
                >
                  <template slot="title" slot-scope="{title}">
                    <span v-if="title.indexOf(searchValue) > -1">
                      {{ title.substr(0, title.indexOf(searchValue)) }}
                      <span class="search-tree-color">{{ searchValue }}</span>
                      {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
                    </span>
                    <span v-else>{{ title }}</span>
                  </template>
                </a-tree>
              </div>
            </div>
          </div>
        </div>
      </a-card-grid>
      <a-card-grid style="width:75%;textAlign:'center';height:100%">
        <div>
          <a-tabs defaultActiveKey="baseInfo" @change="tabsChange">
            <a-tab-pane tab="基础信息" key="baseInfo" forceRender>
              <function-form ref="functionPage" />
            </a-tab-pane>
            <a-tab-pane tab="路由列表" key="routerList" forceRender>
              <div class="table-page-search-wrapper">
                <a-form layout="horizontal" >
                  <a-row :gutter="8">
                    <a-col :md="9" :sm="24">
                      <a-form-item label="路由名" :labelCol="labelCol" :wrapperCol="wrapperCol">
                        <a-input v-model="queryRouterParam.name" placeholder="支持模糊查询"/>
                      </a-form-item>
                    </a-col>
                    <a-col :md="9" :sm="24">
                      <a-form-item label="路由标题" :labelCol="labelCol" :wrapperCol="wrapperCol">
                        <a-input v-model="queryRouterParam.title" placeholder="支持模糊查询"/>
                      </a-form-item>
                    </a-col>
                    <a-col :md="6" :sm="24">
                      <span class="table-page-search-submitButtons" :style="{ float: 'right', overflow: 'hidden' } ">
                        <a-button type="primary" @click="() =>{this.findRouterListBtn()}">查询</a-button>
                        <a-button style="margin-left: 8px" @click="() => {this.clearAll()}">重置</a-button>
                      </span>
                    </a-col>
                  </a-row>
                </a-form>
              </div>
              <vxe-grid
                class="vxe-table-antd"
                resizable
                show-overflow
                row-key
                ref="routerListTable"
                border
                highlight-hover-row
                highlight-current-row
                height="375px"
                size="small"
                row-id="routerId"
                :columns="routerColumn"
                :data="routerTableData"
                :loading="routerLoading"
                :tree-config="{children: 'children', expandAll: true}"
              >
              </vxe-grid>
            </a-tab-pane>
          </a-tabs>
        </div>
      </a-card-grid>
      <a-modal
        title="关联路由信息"
        centered
        style="top: 20px;"
        width="380px"
        destroyOnClose
        v-model="routerVisible"
        cancelText="关闭"
        okText="保存"
        @ok="saveRouter"
      >
        <div style="height:100%">
          <a-input-search style="margin-bottom: 8px" v-model="searchRouterValue" placeholder="请输入路由标题查询" @change="onRouterTreeSearchChange" />
          <div>
            <happy-scroll color="rgba(0,0,0,0.5)" size="5" :min-length-h="400" resize>
              <div style="min-height:400px">
                <a-tree
                  showLine
                  checkable
                  @expand="onExpandRouter"
                  :expandedKeys="expandedRouterKeys"
                  :selectedKeys="selectedRouterKeys"
                  :autoExpandParent="autoExpandRouterParent"
                  :treeData="routerTreeList"
                  v-model="checkedRouterKeys"
                >
                  <template slot="title" slot-scope="{title}">
                    <span v-if="title.indexOf(searchRouterValue) > -1">
                      {{ title.substr(0, title.indexOf(searchRouterValue)) }}
                      <span class="search-tree-color">{{ searchRouterValue }}</span>
                      {{ title.substr(title.indexOf(searchRouterValue) + searchRouterValue.length) }}
                    </span>
                    <span v-else>{{ title }}</span>
                  </template>
                </a-tree>
              </div>
            </happy-scroll>
          </div>
        </div>
      </a-modal>
    </a-card>
    <!-- fixed footer toolbar -->
    <footer-tool-bar>
      <a-button style="margin-left: 8px;" v-if="infoFlag" type="primary" icon="plus" @click="() =>{this.functionAdd()}">同级新增</a-button>
      <a-button style="margin-left: 8px;" v-if="infoFlag" type="primary" icon="plus-circle" @click="() =>{this.childfunctionAdd()}">子级新增</a-button>
      <a-button style="margin-left: 8px;" v-if="infoFlag" type="primary" icon="edit" @click="() =>{this.saveFunction()}">保存</a-button>
      <a-button style="margin-left: 8px" v-if="infoFlag" type="danger" icon="minus" @click="() =>{this.deleteFunction()}">删除</a-button>
      <a-button
        style="margin-left: 8px"
        ghost
        v-if="infoFlag"
        type="primary"
        icon="minus-circle"
        @click="() =>{this.clearFunctionCache()}">清除缓存</a-button>
      <a-button style="margin-left: 8px;" v-if="routerFlag" type="primary" icon="plus" @click="() =>{this.openRouterModel()}">关联路由</a-button>
    </footer-tool-bar>
  </div>
</template>

<script>
import { getRouterTreeList,getFunctionTreeList, getFunctionDetail, getFunctionRouterList, addFunction, editFunction, deleteFunction, moveFunction, clearFunctionCache, saveFuncRouter } from "@/services/system/api"
import FooterToolBar from '@/components/FooterToolbar'
import FunctionForm from '@/pages/system/form/FunctionForm'
import modal from 'ant-design-vue/es/modal'
import { loop, loopParentKey } from '@/utils/util'
function loopExpandCheck (data, checkedKeys, expandedKeys) {
  data.forEach((item) => {
    expandedKeys.push(item.routerId)
    if (item.children) {
      return loopExpandCheck(item.children, checkedKeys, expandedKeys)
    } else {
      checkedKeys.push(item.routerId)
    }
  })
}
export default {
  name: 'RouterManager',
  components: {
    FooterToolBar,
    FunctionForm
  },
  data () {
    return {
      description: '页面管理',
      // 用户查询条件
      queryRouterParam: {},
      labelCol: {
        xs: { span: 24 },
        sm: { span: 7 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 17 }
      },
      // 基础信息操作按钮是否显示
      infoFlag: true,
      functionInfo: null,
      // 路由列表操作按钮是否显示
      routerFlag: false,
      // 功能树
      expandedKeys: [],
      selectedKeys: [],
      searchValue: '',
      autoExpandParent: true,
      functionList: [],
      infoButtonType: '9',
      // 路由列表参数
      routerTableData: [],
      routerLoading: false,
      routerColumn: [
        { field: 'title', title: '路由标题', align: 'center', fixed: 'left', width: 250, treeNode: true },
        { field: 'routerId', title: '路由ID', visible: false, align: 'center', width: 250 },
        { field: 'name', title: '路由名', align: 'center', width: 150 },
        { field: 'parentId', title: '父Id', visible: false, align: 'center', width: 150 },
        { field: 'remarks', title: '备注', align: 'center', width: 250 }
      ],
      // 关联路由弹出框
      routerVisible: false,
      routerTreeList: [],
      expandedRouterKeys: [],
      selectedRouterKeys: [],
      searchRouterValue: '',
      autoExpandRouterParent: true,
      checkedRouterKeys: []
    }
  },
  created () {
    // 初始化数据
    this.findFunctionTreeList()
  },
  methods: {
    // 树节点选择事件
    onFunctionTreeSelect (selectedKeys) {
      this.infoButtonType = '3'
      this.selectedKeys = selectedKeys
      if (selectedKeys && selectedKeys.length > 0) {
        if (this.infoFlag) {
          this.findFuncInfo()
        }
        if (this.routerFlag) {
          this.findFuncInfo()
          this.findRouterList()
        }
      }
    },
    findFuncInfo () {
      if (this.selectedKeys && this.selectedKeys.length > 0) {
        const params = {}
        params.funcId = this.selectedKeys[0]
        setTimeout(() => {
          this.$http.post(getFunctionDetail,params).then((res) => {
            this.functionInfo = res.result
            // 赋值子组件信息
            this.$refs.functionPage.setInitDate(res.result)
          }).catch(() => {
          })
        }, 50)
      }
    },
    findRouterListBtn () {
      if (this.selectedKeys && this.selectedKeys.length > 0) {
        this.findRouterList()
      } else {
        modal.warn({ title: '提示', content: '请先选择需要查询的数据' })
      }
    },
    findRouterList () {
      if (this.selectedKeys && this.selectedKeys.length > 0) {
        this.routerLoading = true
        const params = Object.assign({}, this.queryRouterParam)
        params.funcId = this.selectedKeys[0]
        this.$http.post(getFunctionRouterList,params).then((res) => {
          this.routerTableData = res.result
          this.routerLoading = false
        }).catch(() => {
          this.routerLoading = false
        })
      }
    },
    onExpand (expandedKeys) {
      this.expandedKeys = expandedKeys
      this.autoExpandParent = false
    },
    onTreeSearchChange (e) {
      const value = e.target.value
      if (value) {
        const data = [...this.functionList]
        const expandedKeys = []
        loopParentKey(data, value, expandedKeys)
        this.expandedKeys = expandedKeys
        this.searchValue = value
        this.autoExpandParent = true
      }
    },
    tabsChange (key) {
      if (key === 'baseInfo') {
        this.findFuncInfo()
        this.infoFlag = true
        this.routerFlag = false
      } else if (key === 'routerList') {
        this.findFuncInfo()
        this.findRouterList()
        this.infoFlag = false
        this.routerFlag = true
      }
    },
    findFunctionTreeList () {
      const params = {}
      params.searchText = this.searchValue
      setTimeout(() => {
        this.$http.post(getFunctionTreeList,params).then((res) => {
          const list = res.result.functionList
          list.forEach((item) => {
            item.isLeaf = item.leaf
          })
          this.functionList = list
          this.expandedKeys = res.result.expandedKeys
        }).catch(() => {
        })
      }, 50)
    },
    saveFunction () {
      // 表单验证
      const { $refs: { functionPage } } = this
      const routerForm = new Promise((resolve, reject) => {
        functionPage.form.validateFields((err, values) => {
          if (err) {
            reject(err)
            return
          }
          resolve(values)
        })
      })
      this.errors = []
      Promise.all([routerForm]).then(values => {
        if (values && values.length > 0) {
          const functionData = values[0]
           if (functionData.logFlag) {
            functionData.logFlag = '1'
          } else {
            functionData.logFlag = '0'
          }
          if (functionData.rollbackFlag) {
            functionData.rollbackFlag = '1'
          } else {
            functionData.rollbackFlag = '0'
          }
          if (functionData.auditFlag) {
            functionData.auditFlag = '1'
          } else {
            functionData.auditFlag = '0'
          }
          if (functionData.spanRollbackFlag) {
            functionData.spanRollbackFlag = '1'
          } else {
            functionData.spanRollbackFlag = '0'
          }
          if (functionData.funcId) {
            setTimeout(() => {
              this.$http.post(editFunction,functionData).then((res) => {
                modal.info({ title: '成功提示', content: '修改成功' })
                let oldTitle = ''
                if (this.functionInfo) {
                  oldTitle = this.functionInfo.funcTitle
                }
                // 更新树节点
                if (oldTitle !== res.result.funcTitle) {
                  const dragKey = res.result.funcId
                  const data = [...this.functionList]
                  let dragObj
                  let ar
                  let i
                  loop(data, dragKey, (item, index, arr) => {
                    ar = arr
                    i = index
                    dragObj = item
                  })
                  dragObj.title = res.result.funcTitle
                  dragObj.value = res.result.funcTitle
                  ar.splice(i, 1, dragObj)
                  this.functionList = data
                  this.functionInfo = res.result
                  const newSelect = []
                  newSelect.push(dragKey)
                  this.selectedKeys = newSelect
                }
              }).catch(() => {
                // this.$refs.functionPage.setInitDate(this.functionInfo)
              })
            }, 10)
          } else {
            setTimeout(() => {
              this.$http.post(addFunction,functionData).then((res) => {
                modal.info({ title: '成功提示', content: '新增成功' })
                const funcId = res.result.funcId
                if (this.infoButtonType === '9') {
                  this.findFunctionTreeList()
                  const newSelect = []
                  newSelect.push(funcId)
                  this.selectedKeys = newSelect
                  this.functionInfo = res.result
                  return
                }
                const data = [...this.functionList]
                const dragKey = this.functionInfo.funcId
                const dropKey = res.result.parentId
                const dragObj = {}
                dragObj.key = funcId
                dragObj.title = res.result.funcTitle
                dragObj.value = res.result.funcTitle
                dragObj.parentKey = res.result.parentId
                dragObj.scopedSlots = { title: 'title' }
                if (this.infoButtonType === '1') {
                  // 同级新增
                  let ar
                  let i
                  loop(data, dragKey, (item, index, arr) => {
                    ar = arr
                    i = index
                  })
                  ar.splice(i, 0, dragObj)
                } else if (this.infoButtonType === '2') {
                  // 子级新增
                  loop(data, dropKey, item => {
                    item.children = item.children || []
                    if (!item.expanded) {
                      item.expanded = true
                    }
                    // where to insert 示例添加到尾部，可以是随意位置
                    item.children.push(dragObj)
                  })
                }
                this.functionList = data
                this.$refs.functionPage.setInitDate(res.result)
                const newSelect = []
                newSelect.push(funcId)
                this.selectedKeys = newSelect
                this.functionInfo = res.result
                const newExpandedKeys = this.expandedKeys
                if (newExpandedKeys && newExpandedKeys.length > 0) {
                  if (newExpandedKeys.indexOf(dropKey) <= 0) {
                    newExpandedKeys.push(dropKey)
                    this.expandedKeys = newExpandedKeys
                  }
                }
              }).catch(() => {
              })
            }, 10)
          }
        }
      }).catch(() => {
        const errors = Object.assign({}, functionPage.form.getFieldsError())
        const tmp = { ...errors }
        this.errorList(tmp)
      })
    },
    errorList (errors) {
      if (!errors || errors.length === 0) {
        return
      }
      this.errors = Object.keys(errors)
        .filter(key => errors[key])
        .map(key => ({
          key: key,
          message: errors[key][0]
        }))
    },
    functionAdd () {
      if (this.functionInfo) {
        this.infoButtonType = '1'
        const params = {}
        params.parentId = this.functionInfo.parentId
        params.parentTitle = this.functionInfo.parentTitle
        params.funcId = ''
        params.status = '1'
        params.publicFlag = '0'
        params.nodeType = '0'
        params.api = this.functionInfo.api
        params.classPath = this.functionInfo.classPath
        params.orderNo = this.functionInfo.orderNo
        params.rate = this.functionInfo.rate
        this.$refs.functionPage.setInitDate(params)
      } else {
        modal.warn({ title: '提示', content: '请先选择某一节点' })
      }
    },
    childfunctionAdd () {
      if (this.functionInfo) {
        const nodeType = this.functionInfo.nodeType
        if (nodeType && nodeType === '1') {
          modal.warn({ title: '提示', content: '节点类型是叶子，不能添加子节点' })
        } else {
          this.infoButtonType = '2'
          const params = {}
          params.parentId = this.functionInfo.funcId
          params.parentTitle = this.functionInfo.funcTitle
          params.status = '1'
          params.publicFlag = '0'
          params.nodeType = '0'
          params.funcId = ''
          params.orderNo = ''
          let rate = this.functionInfo.rate
          if (rate) {
            rate = rate + 1
          } else {
            rate = 1
          }
          params.rate = rate
          this.$refs.functionPage.setInitDate(params)
        }
      } else {
        modal.warn({ title: '提示', content: '请先选择某一节点' })
      }
    },
    deleteFunction () {
      if (this.functionInfo) {
        const params = {}
        params.funcId = this.functionInfo.funcId
        setTimeout(() => {
          this.$http.post(deleteFunction,params).then(() => {
            modal.info({ title: '成功提示', content: '删除成功' })
            const data = [...this.functionList]
            loop(data, this.functionInfo.funcId, (item, index, arr) => {
              arr.splice(index, 1)
            })
            this.functionList = data
            this.selectedKeys = []
            this.functionInfo = null
            this.infoButtonType = '9'
            this.$refs.functionPage.setInitDate(null)
          }).catch(() => {
          })
        }, 100)
      } else {
        modal.warn({ title: '提示', content: '请先选择需要删除的数据' })
      }
    },
    onDragEnter (info) {
      console.log(info)
      // expandedKeys 需要受控时设置
      // this.expandedKeys = info.expandedKeys
    },
    onDrop (info) {
      console.log(info)
      const dropKey = info.node.eventKey
      const dragKey = info.dragNode.eventKey
      const dropPos = info.node.pos.split('-')
      const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
      const params = {}
      params.dropKey = dropKey
      params.dragKey = dragKey
      params.dropPosition = dropPosition
      setTimeout(() => {
        this.$http.post(moveFunction,params).then((res) => {
          const data = [...this.functionList]
          // Find dragObject
          let dragObj
          loop(data, dragKey, (item, index, arr) => {
            arr.splice(index, 1)
            dragObj = item
          })
          if (!info.dropToGap) {
            // Drop on the content
            loop(data, dropKey, item => {
              item.children = item.children || []
              // where to insert 示例添加到尾部，可以是随意位置
              item.children.push(dragObj)
            })
          } else if (
            (info.node.children || []).length > 0 && // Has children
            info.node.expanded && // Is expanded
            dropPosition === 1 // On the bottom gap
          ) {
            loop(data, dropKey, item => {
              item.children = item.children || []
              // where to insert 添加到第一行
              item.children.unshift(dragObj)
            })
          } else {
            let ar
            let i
            loop(data, dropKey, (item, index, arr) => {
              ar = arr
              i = index
            })
            if (dropPosition === -1) {
              ar.splice(i, 0, dragObj)
            } else {
              ar.splice(i + 1, 0, dragObj)
            }
          }
          this.functionList = data
          this.functionInfo = res.result
          this.$refs.functionPage.setInitDate(res.result)
        }).catch(() => {
        })
      }, 50)
    },
    clearFunctionCache () {
        const params = {}
        if (this.functionInfo) {
          params.funcId = this.functionInfo.funcId
        }
        setTimeout(() => {
          this.$http.post(clearFunctionCache,params).then(() => {
            modal.info({ title: '成功提示', content: '清除缓存成功' })
          }).catch(() => {
          })
        }, 100)
      
    },
    openRouterModel () {
      // 打开添加路由页面
      if (this.functionInfo) {
        const nodeType = this.functionInfo.nodeType
        if (nodeType === '0') {
          modal.warn({ title: '提示', content: '节点不能关联路由' })
          return
        }
        const publicFlag = this.functionInfo.publicFlag
        if (publicFlag === '1') {
          modal.warn({ title: '提示', content: '公共方法无需关联路由' })
        } else {
          // 获取路由树
          this.findRouterTreeList()
          // 添加选中节点
          this.routerVisible = true
        }
      } else {
        modal.warn({ title: '提示', content: '请先选择需要关联路由的功能数据' })
      }
    },
    onExpandRouter (expandedKeys) {
      this.expandedRouterKeys = expandedKeys
      this.autoExpandRouterParent = false
    },
    saveRouter () {
      // 获取选中的路由信息
      const params = {}
      params.routerIds = this.checkedRouterKeys
      params.funcId = this.functionInfo.funcId
      setTimeout(() => {
        this.$http.post(saveFuncRouter,params).then(() => {
          this.findRouterList()
          this.routerVisible = false
        }).catch(() => {
        })
      }, 50)
    },
    findRouterTreeList () {
      this.searchRouterValue = ''
      const params = {}
      params.searchText = this.searchRouterValue
      setTimeout(() => {
        this.$http.post(getRouterTreeList,params).then((res) => {
          const data = [...res.result.routerList]
          if (data) {
            this.loopCheckDisable(data)
            this.routerTreeList = data
            this.checkedRouterKeys = []
            this.expandedRouterKeys = res.result.expandedKeys
            if (this.routerTableData && this.routerTableData.length > 0) {
              // 设置选中节点
              const checkedKeys = []
              // 设置展开节点
              const expandedRouterKeys = []
              loopExpandCheck(this.routerTableData, checkedKeys, expandedRouterKeys)
              this.checkedRouterKeys = checkedKeys
              this.expandedRouterKeys = expandedRouterKeys
              this.autoExpandRouterParent = true
            }
          }
        }).catch(() => {
        })
      }, 50)
    },
    loopCheckDisable (data) {
      data.forEach((item) => {
        if (item.children) {
          item.disabled = true
          this.loopCheckDisable(item.children)
        }
      })
    },
    onRouterTreeSearchChange (e) {
      const value = e.target.value
      if (value) {
        const data = [...this.routerTreeList]
        const expandedKeys = []
        loopParentKey(data, value, expandedKeys)
        this.expandedRouterKeys = expandedKeys
        this.searchRouterValue = value
        this.autoExpandRouterParent = true
      }
    },
    clearAll () {
      this.queryRouterParam = {}
      this.findRouterList()
      setTimeout(() => {
        this.$refs.routerListTable.clearSelection()
        this.$refs.routerListTable.clearSelectReserve()
      }, 50)
    }
  }
}
</script>
<style lang="less" scoped>
@import "~ant-design-vue/lib/style/themes/default.less";
.search-tree-color {
  color : @primary-color
}
</style>
